package admin

import (
	"baokaobang/conf"
	"baokaobang/datasourse"
	"baokaobang/models"
	"baokaobang/utils"
	"encoding/json"
	"fmt"
	"github.com/360EntSecGroup-Skylar/excelize"
	"github.com/kataras/iris/v12"
	"github.com/kataras/iris/v12/mvc"
	"strings"
)

type AdmissionData struct {
	Ctx iris.Context
}

type AdmissionDataExcelCreate struct {
	Batch    int    `json:"batch"`
	Subject  int    `json:"subject"`
	ExcelUrl string `json:"excelUrl"`
}

type CreateAdmissionData struct {
	Id        string `json:"id"`
	Year      int    `json:"year"`
	Subject   int    `json:"subject"`
	Batch     int    `json:"batch"`
	CollegeId int64  `json:"collegeId"`
	MajorName string `json:"majorName"`
	MajorCode string `json:"majorCode"`
	PlanNum   string `json:"planNum"`
	ActualNum string `json:"actualNum"`
	MaxScore  string `json:"maxScore"`
	MinScore  string `json:"minScore"`
}

type AdmissionDataListParam struct {
	Year      int   `json:"year"`
	Subject   int   `json:"subject"`
	Batch     int   `json:"batch"`
	CollegeId int64 `json:"collegeId"`
	PerPage   int   `json:"perPage"`
	CurPage   int   `json:"curPage"`
}

func (c *AdmissionData) OptionsExcel() mvc.Response {
	return mvc.Response{
		Code: 204,
	}
}

func (c *AdmissionData) PostExcel() interface{} {
	admissionDataExcelCreate := AdmissionDataExcelCreate{}
	content, err := c.Ctx.GetBody()
	if err != nil {
		return utils.CommonRes(1000, fmt.Sprintf("接受请求参数出错:%s", err.Error()), "")
	}
	err = json.Unmarshal(content, &admissionDataExcelCreate)
	if err != nil {
		return utils.CommonRes(1000, fmt.Sprintf("参数解析出错:%s", err.Error()), "")
	}

	if admissionDataExcelCreate.Subject <= 0 {
		return utils.CommonRes(1000, "请选择科目", "")
	}
	if admissionDataExcelCreate.Batch <= 0 {
		return utils.CommonRes(1000, "请选择批次", "")
	}
	if len(admissionDataExcelCreate.ExcelUrl) <= 0 {
		return utils.CommonRes(1000, "请上传excel文件", "")
	}

	db, err := datasourse.NewMasterOrm()
	if err != nil {
		return utils.CommonRes(1000, fmt.Sprintf("无法连接数据库：%s", err.Error()), "")
	}

	sess := db.NewSession()
	defer sess.Close()
	err = sess.Begin()
	if err != nil {
		return utils.CommonRes(1000, fmt.Sprintf("数据库事务开启失败：%s", err.Error()), "")
	}

	filePath := fmt.Sprintf("%s%s", conf.UploadPrefix.Backend, admissionDataExcelCreate.ExcelUrl)
	f, err := excelize.OpenFile(filePath)
	if err != nil {
		return utils.CommonRes(1000, fmt.Sprintf("上传的文件无法打开:%s", err.Error()), "")
	}

	batch := admissionDataExcelCreate.Batch
	subject := admissionDataExcelCreate.Subject

	sheetList := f.GetSheetMap()
	for _, sheet := range sheetList {
		sheet = strings.TrimSpace(sheet)
		collegeCode := strings.Split(sheet, "-")[0]
		college := new(models.College)
		ok, err := sess.Where("code = ?", collegeCode).Get(college)
		if err != nil {
			return utils.CommonRes(1000, fmt.Sprintf("查询%s出错:%s", sheet, err.Error()), "")
		}
		if !ok {
			return utils.CommonRes(1000, fmt.Sprintf("系统中没有找到%s", sheet), "")
		}

		rows := f.GetRows(sheet)
		for i, row := range rows {
			if i == 0 {
				continue
			}

			year := utils.Atoi(row[0])
			minScore := utils.Atoi(row[6])

			minRank := new(models.Rank)
			ok, err = sess.Where("year = ? and subject = ? and score = ?", year, subject, minScore).Get(minRank)
			if err != nil {
				return utils.CommonRes(1000, fmt.Sprintf("%d %s %d分无法查询到对应位次：%s", year, models.RankSubject[subject], minScore, err.Error()), "")
			}
			if !ok {
				return utils.CommonRes(1000, fmt.Sprintf("%d %s %d分无法查询到对应位次", year, models.RankSubject[subject], minScore), "")
			}
			minRankArr := strings.Split(minRank.Section, "~")

			admissionData := new(models.AdmissionData)
			admissionData.Year = year
			admissionData.Subject = subject
			admissionData.Batch = batch
			admissionData.CollegeId = college.Id
			admissionData.MajorCode = row[1]
			admissionData.MajorName = row[2]
			admissionData.MinScore = utils.Atoi(row[6])
			admissionData.MinScoreHigh = utils.Atoi(minRankArr[0])
			admissionData.MinScoreLow = utils.Atoi(minRankArr[1])
			_, err = sess.InsertOne(admissionData)
			if err != nil {
				return utils.CommonRes(1000, fmt.Sprintf("数据导入失败：%s", err.Error()), "")
			}
		}
	}
	sess.Commit()

	return utils.CommonRes(20000, "数据导入成功", "")
}

func (c *AdmissionData) OptionsExcel1() mvc.Response {
	return mvc.Response{
		Code: 204,
	}
}

func (c *AdmissionData) PostExcel1() interface{} {
	admissionDataExcelCreate := AdmissionDataExcelCreate{}
	content, err := c.Ctx.GetBody()
	if err != nil {
		return utils.CommonRes(1000, fmt.Sprintf("接受请求参数出错:%s", err.Error()), "")
	}
	err = json.Unmarshal(content, &admissionDataExcelCreate)
	if err != nil {
		return utils.CommonRes(1000, fmt.Sprintf("参数解析出错:%s", err.Error()), "")
	}

	if admissionDataExcelCreate.Subject <= 0 {
		return utils.CommonRes(1000, "请选择科目", "")
	}
	if len(admissionDataExcelCreate.ExcelUrl) <= 0 {
		return utils.CommonRes(1000, "请上传excel文件", "")
	}

	db, err := datasourse.NewMasterOrm()
	if err != nil {
		return utils.CommonRes(1000, fmt.Sprintf("无法连接数据库：%s", err.Error()), "")
	}

	sess := db.NewSession()
	defer sess.Close()
	err = sess.Begin()
	if err != nil {
		return utils.CommonRes(1000, fmt.Sprintf("数据库事务开启失败：%s", err.Error()), "")
	}

	filePath := fmt.Sprintf("%s%s", conf.UploadPrefix.Backend, admissionDataExcelCreate.ExcelUrl)
	f, err := excelize.OpenFile(filePath)
	if err != nil {
		return utils.CommonRes(1000, fmt.Sprintf("上传的文件无法打开:%s", err.Error()), "")
	}

	year := ""
	universityName := ""
	var university models.University

	sheetList := f.GetSheetMap()
	for _, sheet := range sheetList {
		sheet = strings.TrimSpace(sheet)
		rows := f.GetRows(sheet)
		for i, row := range rows {
			if i == 0 {
				continue
			}

			if len(row[0]) == 4 {
				year = strings.TrimSpace(row[0])
			} else if len(row[0]) <= 0 {

			} else {
				universityName = strings.TrimSpace(row[0])
				university = models.University{}
				ok, err := sess.Where("name = ?", universityName).Get(&university)
				if err != nil {
					return utils.CommonRes(1000, fmt.Sprintf("查询%s出错:%s", universityName, err.Error()), "")
				}
				if !ok {
					return utils.CommonRes(1000, fmt.Sprintf("系统中没有找到%s", universityName), "")
				}
				continue
			}

			minScore := utils.Atoi(strings.TrimSpace(row[6]))

			minRank := new(models.Rank)
			ok, err := sess.Where("year = ? and subject = ? and score = ?", year, admissionDataExcelCreate.Subject, minScore).Get(minRank)
			if err != nil {
				return utils.CommonRes(1000, fmt.Sprintf("%s年%s%d分无法查询到对应位次：%s", year, models.RankSubject[admissionDataExcelCreate.Subject], minScore, err.Error()), "")
			}
			if !ok {
				return utils.CommonRes(1000, fmt.Sprintf("%s年%s%d分无法查询到对应位次", year, models.RankSubject[admissionDataExcelCreate.Subject], minScore), "")
			}
			minRankArr := strings.Split(minRank.Section, "~")

			admissionData := new(models.AdmissionData)
			admissionData.Year = utils.Atoi(year)
			admissionData.Subject = admissionDataExcelCreate.Subject
			admissionData.CollegeId = university.Id
			admissionData.MajorCode = strings.TrimSpace(row[1])
			admissionData.MajorName = strings.TrimSpace(row[2])
			admissionData.MinScore = minScore
			admissionData.MinScoreHigh = utils.Atoi(minRankArr[0])
			admissionData.MinScoreLow = utils.Atoi(minRankArr[1])
			_, err = sess.InsertOne(admissionData)
			if err != nil {
				return utils.CommonRes(1000, fmt.Sprintf("数据导入失败：%s", err.Error()), "")
			}
		}
	}
	sess.Commit()

	return utils.CommonRes(20000, "数据导入成功", "")
}

func (c *AdmissionData) OptionsList() mvc.Response {
	return mvc.Response{
		Code: 204,
	}
}

func (c *AdmissionData) PostList() interface{} {
	admissionDataListParam := AdmissionDataListParam{}
	content, err := c.Ctx.GetBody()
	if err != nil {
		return utils.CommonRes(1000, fmt.Sprintf("接收请求参数出错:%s", err.Error()), "")
	}
	err = json.Unmarshal(content, &admissionDataListParam)
	if err != nil {
		return utils.CommonRes(1000, fmt.Sprintf("解析请求参数出错:%s", err.Error()), "")
	}

	db, err := datasourse.NewMasterOrm()
	if err != nil {
		return utils.CommonRes(1000, fmt.Sprintf("无法连接数据库:%s", err.Error()), "")
	}

	start := (admissionDataListParam.CurPage - 1) * admissionDataListParam.PerPage
	admissionDataList := make([]models.AdmissionDataObj, 0)
	sess := db.Table(new(models.AdmissionData)).Alias("ad").
		Join("INNER", []string{"college", "c"}, "ad.college_id = c.id").
		Limit(admissionDataListParam.PerPage, start)
	if admissionDataListParam.Year > 0 {
		sess = sess.Where("ad.year = ?", admissionDataListParam.Year)
	}
	if admissionDataListParam.Subject > 0 {
		sess = sess.Where("ad.subject = ?", admissionDataListParam.Subject)
	}
	if admissionDataListParam.Batch > 0 {
		sess = sess.Where("ad.batch = ?", admissionDataListParam.Batch)
	}
	if admissionDataListParam.CollegeId > 0 {
		sess = sess.Where("ad.college_id = ?", admissionDataListParam.CollegeId)
	}
	err = sess.Find(&admissionDataList)
	if err != nil {
		return utils.CommonRes(1000, fmt.Sprintf("无法获取院校专业录取数据列表:%s", err.Error()), "")
	}

	countSess := db.Where("id > ?", 0)
	if admissionDataListParam.Year > 0 {
		countSess = countSess.Where("year = ?", admissionDataListParam.Year)
	}
	if admissionDataListParam.Subject > 0 {
		countSess = countSess.Where("subject = ?", admissionDataListParam.Subject)
	}
	if admissionDataListParam.Subject > 0 {
		countSess = countSess.Where("batch = ?", admissionDataListParam.Batch)
	}
	if admissionDataListParam.CollegeId > 0 {
		countSess = countSess.Where("college_id = ?", admissionDataListParam.CollegeId)
	}
	total, err := countSess.Count(new(models.AdmissionData))
	if err != nil {
		return utils.CommonRes(1000, fmt.Sprintf("无法获取院校专业录取数据列表:%s", err.Error()), "")
	}

	for i, item := range admissionDataList {
		admissionDataList[i].SubjectShow = models.RankSubject[item.Subject]
		admissionDataList[i].BatchShow = models.AdmissionDataBatch[item.Batch]
		admissionDataList[i].MinSection = fmt.Sprintf("%d~%d", item.MinScoreHigh, item.MinScoreLow)
	}

	data := map[string]interface{}{
		"total": total,
		"list":  admissionDataList,
	}

	return utils.CommonRes(20000, "成功获取大学录取数据列表", data)
}

func (c *AdmissionData) OptionsEdit() mvc.Response {
	return mvc.Response{
		Code: 204,
	}
}

func (c *AdmissionData) PostEdit() interface{} {
	createAdmissionData := CreateAdmissionData{}
	content, err := c.Ctx.GetBody()
	if err != nil {
		return utils.CommonRes(1000, fmt.Sprintf("接收请求参数出错:%s", err.Error()), "")
	}
	err = json.Unmarshal(content, &createAdmissionData)
	if err != nil {
		return utils.CommonRes(1000, fmt.Sprintf("解析请求参数出错:%s", err.Error()), "")
	}

	if len(createAdmissionData.Id) <= 0 {
		return utils.CommonRes(1000, "请提供录取数据id", "")
	}
	if createAdmissionData.Year <= 0 {
		return utils.CommonRes(1000, "请选择年份", "")
	}
	if createAdmissionData.Subject <= 0 {
		return utils.CommonRes(1000, "请选择科目", "")
	}
	if createAdmissionData.Batch <= 0 {
		return utils.CommonRes(1000, "请选择批次", "")
	}
	if createAdmissionData.CollegeId <= 0 {
		return utils.CommonRes(1000, "请选择院校", "")
	}
	if len(createAdmissionData.MajorName) <= 0 {
		return utils.CommonRes(1000, "请输入专业名称", "")
	}
	if len(createAdmissionData.MajorCode) <= 0 {
		return utils.CommonRes(1000, "请输入专业代码", "")
	}
	if len(createAdmissionData.PlanNum) <= 0 {
		return utils.CommonRes(1000, "请输入计划人数", "")
	}
	if len(createAdmissionData.ActualNum) <= 0 {
		return utils.CommonRes(1000, "请输入录取人数", "")
	}
	if len(createAdmissionData.MaxScore) <= 0 {
		return utils.CommonRes(1000, "请输入录取最高分", "")
	}
	if len(createAdmissionData.MinScore) <= 0 {
		return utils.CommonRes(1000, "请输入录取最低分", "")
	}

	db, err := datasourse.NewMasterOrm()
	if err != nil {
		return utils.CommonRes(1000, fmt.Sprintf("无法连接数据库:%s", err.Error()), "")
	}

	maxRank := new(models.Rank)
	ok, err := db.Where("year = ? and subject = ? and score = ?", createAdmissionData.Year, createAdmissionData.Subject, createAdmissionData.MaxScore).Get(maxRank)
	if err != nil {
		return utils.CommonRes(1000, fmt.Sprintf("%s分无法查询到对应位次：%s", createAdmissionData.MaxScore, err.Error()), "")
	}
	if !ok {
		return utils.CommonRes(1000, fmt.Sprintf("%s分无法查询到对应位次", createAdmissionData.MaxScore), "")
	}
	maxRankArr := strings.Split(maxRank.Section, "~")

	minRank := new(models.Rank)
	ok, err = db.Where("year = ? and subject = ? and score = ?", createAdmissionData.Year, createAdmissionData.Subject, createAdmissionData.MinScore).Get(minRank)
	if err != nil {
		return utils.CommonRes(1000, fmt.Sprintf("%s分无法查询到对应位次：%s", createAdmissionData.MinScore, err.Error()), "")
	}
	if !ok {
		return utils.CommonRes(1000, fmt.Sprintf("%s分无法查询到对应位次", createAdmissionData.MinScore), "")
	}
	minRankArr := strings.Split(minRank.Section, "~")

	updateData := map[string]interface{}{
		"year":           createAdmissionData.Year,
		"subject":        createAdmissionData.Subject,
		"batch": createAdmissionData.Batch,
		"college_id":  createAdmissionData.CollegeId,
		"major_name":     createAdmissionData.MajorName,
		"major_code":     createAdmissionData.MajorCode,
		"plan_num":       createAdmissionData.PlanNum,
		"actual_num":     createAdmissionData.ActualNum,
		"max_score":      createAdmissionData.MaxScore,
		"max_score_high": maxRankArr[0],
		"max_score_low":  maxRankArr[1],
		"min_score":      createAdmissionData.MinScore,
		"min_score_high": minRankArr[0],
		"min_score_low":  minRankArr[1],
	}

	_, err = db.Table(new(models.AdmissionData)).ID(createAdmissionData.Id).Update(updateData)
	if err != nil {
		return utils.CommonRes(1000, "操作失败", "")
	}

	return utils.CommonRes(20000, "操作成功", "")
}

func (c *AdmissionData) OptionsDetail() mvc.Response {
	return mvc.Response{
		Code: 204,
	}
}

func (c *AdmissionData) PostDetail() interface{} {
	editParam := utils.EditParam{}
	content, err := c.Ctx.GetBody()
	if err != nil {
		return utils.CommonRes(1000, fmt.Sprintf("接收请求参数出错:%s", err.Error()), "")
	}
	err = json.Unmarshal(content, &editParam)
	if err != nil {
		return utils.CommonRes(1000, fmt.Sprintf("解析请求参数出错:%s", err.Error()), "")
	}

	if len(editParam.Id) <= 0 {
		return utils.CommonRes(1000, "请提供专业录取数据id", "")
	}

	db, err := datasourse.NewMasterOrm()
	if err != nil {
		return utils.CommonRes(1000, fmt.Sprintf("无法连接数据库:%s", err.Error()), "")
	}

	admissionData := new(models.AdmissionData)
	ok, err := db.ID(editParam.Id).Get(admissionData)
	if err != nil {
		return utils.CommonRes(1000, fmt.Sprintf("信息获取失败:%s", err.Error()), "")
	}
	if !ok {
		return utils.CommonRes(1000, "信息获取失败", "")
	}

	return utils.CommonRes(20000, "信息获取成功", admissionData)
}

func (c *AdmissionData) OptionsDel() mvc.Response {
	return mvc.Response{
		Code: 204,
	}
}

func (c *AdmissionData) PostDel() interface{} {
	delParam := utils.DelParam{}
	content, err := c.Ctx.GetBody()
	if err != nil {
		return utils.CommonRes(1000, fmt.Sprintf("接受请求参数出错:%s", err.Error()), "")
	}
	err = json.Unmarshal(content, &delParam)
	if err != nil {
		return utils.CommonRes(1000, fmt.Sprintf("参数解析出错：%s", err.Error()), "")
	}

	if len(delParam.Ids) <= 0 {
		return utils.CommonRes(1000, "请提供要删除项的id", "")
	}

	db, err := datasourse.NewMasterOrm()
	if err != nil {
		return utils.CommonRes(1000, fmt.Sprintf("无法连接数据库：%s", err.Error()), "")
	}

	ids := strings.Split(delParam.Ids, ",")
	for _, id := range ids {
		admissionData := new(models.AdmissionData)
		db.ID(id).Get(admissionData)
		db.ID(id).Delete(admissionData)
	}

	return utils.CommonRes(20000, "操作成功", "")
}
